package com.atXiao.video.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import com.atXiao.video.common.constant.MyOss;
import com.atXiao.video.common.constant.MyVideoPath;
import com.atXiao.video.common.constant.OssClient;
import com.atXiao.video.entity.Video;
import com.atXiao.video.entity.req.common.PageReq;
import com.atXiao.video.entity.req.video.VideoDownloadReq;
import com.atXiao.video.entity.req.video.VideoUploadReq;
import com.atXiao.video.entity.resp.video.VideoDownloadResp;
import com.atXiao.video.mapper.VideoMapper;
import com.atXiao.video.utils.FFmpegUtils;
import com.atXiao.video.utils.RedisUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atXiao.video.service.VideoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * Video服务实现类
 * </p>
 *
 * @author lixiaoxiao
 * @since 2022-10-28
 */
@Service
public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements VideoService {
    //调试日志
    private final static Logger logger = LoggerFactory.getLogger(VideoServiceImpl.class);


    private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    private SimpleDateFormat filePathFormat = new SimpleDateFormat("yyyyMMdd");

    @Autowired
    MyOss oss;
    @Autowired
    OssClient ossClient;
    @Autowired
    RedisUtils redisUtils;
    @Autowired
    MyVideoPath myVideoPath;


    @Override
    public void uploadVideo(VideoUploadReq videoUploadReq) {
        //视频上传的本地路径
        String localPath = myVideoPath.getMyPath();
        OSS ossClient = this.ossClient.getOssClient();

        MultipartFile videoFile = videoUploadReq.getVideoFile();

        //1.将视频文件上传至阿里云
        //获取视频文件原始名称
        String originalFullName = videoFile.getOriginalFilename();
        String[] split = videoFile.getContentType().split("\\/");
//            String[] split = originalFullName.split(".");
        String originalName = originalFullName.split("\\.")[0];
        String fileExtension = split[1];
        //新文件的名称为文件的原始名+时间戳（防止并发提交的时候出现文件名重复的问题）
        String filePath = filePathFormat.format(new Date()) + "/";
        String newName = originalName + sdf.format(new Date()) + "." + fileExtension;
        String wholeVideoName = filePath + newName;
        //oss以时间日期进行区分不同日期上传的视频

        PutObjectResult result = null;
        try {
            result = ossClient.putObject(oss.getBUCKET_NAME(), wholeVideoName, videoFile.getInputStream());
            //将视频设置为公共读
            ossClient.setObjectAcl(oss.getBUCKET_NAME(), wholeVideoName, CannedAccessControlList.PublicRead);
            logger.info("上传阿里云完成，视频路径:" + wholeVideoName);
            System.out.println(result);
            //2.将视频文件在本地服务器存储一份
            File file = new File(localPath, newName);
            videoFile.transferTo(file);
            logger.info("视频上传本地完成");
            //3.利用工具类生成视频的封面(截取视频某一帧的画面)
            String coverAddress = FFmpegUtils.grabberVideoFramer(newName, localPath);
            logger.info("视频封面地址:" + coverAddress);
            System.out.println("coverAddress:" + coverAddress);
            //视频的封面名称
            String coverName = "cover" + sdf.format(new Date()) + ".jpg";
            //将视频的封面图片上传至阿里云
            //oss中图片存储的路径
            String aliCoverPath = filePath + coverName;
            ossClient.putObject(oss.getBUCKET_NAME(), aliCoverPath, new FileInputStream(coverAddress));
            //获取视频时长
            String videoTime = FFmpegUtils.formatDuration(FFmpegUtils.videoDuration(file));
            //4.设置封面的读写权限为公共读
            ossClient.setObjectAcl(oss.getBUCKET_NAME(), aliCoverPath, CannedAccessControlList.PublicRead);

            //组装封面图片的访问路径
            String coverPublicPath = "https://" + oss.getBUCKET_IP() + "/" + aliCoverPath;
            logger.info("封面公网访问路径:" + coverPublicPath);

            //直接入库
            Video video = new Video();
            //视频标题
            video.setTitle(videoUploadReq.getTitle());
            //视频时长
            video.setTime(videoTime);
            //视频封面图片
            video.setImg(coverPublicPath);
            //上传的用户
            video.setUsername(videoUploadReq.getUsername());
            //视频的逻辑地址
            video.setUrl(wholeVideoName);
            //视频介绍
            video.setIntroduction(videoUploadReq.getIntroduction());
            //视频状态,默认为0
            video.setStatus(0);
            this.save(video);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public VideoDownloadResp downloadVideo(VideoDownloadReq videoDownloadReq) {
        //视频下载响应类
        VideoDownloadResp downloadResp = new VideoDownloadResp();
        //获取要查询的视频编号
        Long id = videoDownloadReq.getId();
        //查询返回的结果
        Video video = this.getById(id);
        //没有bucketName的视频名称
        String url = video.getUrl();
        //从bucket中获取出该视频的完整访问路径
        OSS ossClient = this.ossClient.getOssClient();
        //构建下载请求
        GetObjectRequest videoRequest = new GetObjectRequest(oss.getBUCKET_NAME(), url);
        //下载结果
        OSSObject videoRes = ossClient.getObject(videoRequest);
        //TODO 获取视频地址(只能获取到公共读的)
        String videoUri = videoRes.getResponse().getUri();

        //属性对拷
        BeanUtils.copyProperties(video, downloadResp);
        downloadResp.setUrl(videoUri);
        return downloadResp;
    }

    @Override
    public List<VideoDownloadResp> listVideoInfo(PageReq pageReq) {
        ArrayList<VideoDownloadResp> videoResList = new ArrayList<>();
        //当前页码
        Long currentPage = pageReq.getCurrentPage();
        //一页展示数量
        Long pageSize = pageReq.getPageSize();
        Page<Video> videoPage = new Page<>();
        videoPage.setCurrent(ObjectUtils.isEmpty(currentPage) ? 0L : currentPage);
        videoPage.setSize(ObjectUtils.isEmpty(pageSize) ? 10L : pageSize);
        //查询返回的分页对象
        IPage<Video> videoPageRes = this.page(videoPage);
        List<Video> records = videoPageRes.getRecords();
        for (Video record : records) {
            VideoDownloadResp videoDownloadResp = new VideoDownloadResp();
            BeanUtils.copyProperties(record, videoDownloadResp);
            videoResList.add(videoDownloadResp);
        }

        //返回查询记录数
        return videoResList;
    }
}
